package com.meme.editor.gui.sprite2d;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Point;
import java.awt.SystemColor;
import java.awt.Cursor;

import javax.swing.AbstractAction;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;

import org.apache.log4j.Logger;

import java.awt.event.ActionEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;

//import com.meme.editor.ObjectWithProperties;
import com.meme.editor.event.EntityChangedEvent;
import com.meme.editor.event.EntityObjectListener;
import com.meme.editor.gui.EntityChildrenListView;
import com.meme.editor.gui.PropertyEditPanel;
import com.meme.editor.gui.sprite2d.ModuleGroupView_Icons.ReplaceModuleInPartAction;
import com.meme.editor.model.sprite2d.Module;
import com.meme.editor.model.sprite2d.ModuleRef;
import com.meme.editor.model.sprite2d.PureModuleGroup;
import com.meme.editor.model.sprite2d.ModuleImage;
import com.meme.editor.model.sprite2d.PureModule;
import com.meme.editor.EntityObject;

import com.meme.util.GuiUtil;;

public class ModuleGroupView_Bird extends JPanel 
	implements EntityObjectListener, AncestorListener, 
	           MouseListener, MouseMotionListener, MouseWheelListener
{
	static Logger logger = Logger.getLogger (ModuleGroupView_Bird.class);
	
	public static final int Margin_EditView = 20;
	
	
	PureModuleGroup mPureModuleGroup;
	
	static final int MaxScale = 8;
	static final int MinScale = 1;
	static final int DefaultScale = 3;
	// for edit mode
	int mScale = DefaultScale;

	int mImageLeft; // with scale
	int mImageTop;
	
	int mImageWidth; // without scale
	int mImageHeight;
	
	PureModule mSelectedModule;
	
	
	public ModuleGroupView_Bird (PureModuleGroup moduleGroup)
	{
		mPureModuleGroup = moduleGroup;
		
		addAncestorListener (this);
		addMouseListener (this);
		addMouseMotionListener (this);
		addMouseWheelListener (this);
	}
	
	
	EntityChildrenListView mChildrenListView;
//	PropertyEditPanel      mChildPropertyView;
	
	public void setChildrenListView (EntityChildrenListView childrenView)
	{
		mChildrenListView = childrenView;
	}
	
//	public void setChildPropertyView (PropertyEditPanel propertyView)
//	{
//		mChildPropertyView = propertyView;
//	}
	
	
	boolean mReadOnly = false;
	public void setReadOnly (boolean bReadOnly)
	{
		mReadOnly = bReadOnly;
		if ( mReadOnly )
			mScale = 1;
	}
	
	@Override
	public void paintComponent (Graphics g)
	{
		updateSomeValues ( mScale, 0, 0);
		
		int viewWidth = getWidth ();
		int viewHeight = getHeight ();
		
		
		g.setColor ( SystemColor.window );
		g.fillRect(0, 0, viewWidth, viewHeight);
		
		ModuleImage pureImage = mPureModuleGroup.getModuleImage();
		if ( pureImage != null && pureImage.isValid() )
		{			
			// paint image
			int x = mImageLeft + viewWidth / 2;
			int y = mImageTop + viewHeight / 2;
			int w = pureImage.getWidth() * mScale;
			int h = pureImage.getHeight() * mScale;

			g.drawImage(pureImage.getImage(), x, y, w, h, this);
			pureImage.render(g);
			
			// paint modules
			for (int i = mPureModuleGroup.getChildrenCount() - 1; i >= 0; -- i)
				drawModuleFrame (g, (PureModule) mPureModuleGroup.getChildByIndex (i), Color.green );
			if ( mTempModule != null )
				drawModuleFrame (g, mTempModule, Color.red);
		}
	}
	
	Point mModuleStart = new Point ();
	void drawModuleFrame (Graphics g, PureModule module, Color color)
	{
		mModuleStart.setLocation (module.getX(), module.getY());
		_2dp (mModuleStart);
		
		g.setColor (color);
		g.drawRect (mModuleStart.x, mModuleStart.y, module.getWidth() * mScale, module.getHeight() * mScale);
		
		if ( module == mSelectedModule )
		{
			//Color oldcolor = g.getColor();
			g.setColor( new Color(0x7f0000ff, true) );
			g.fillRect(mModuleStart.x, mModuleStart.y, module.getWidth() * mScale - 1, module.getHeight() * mScale - 1);
			//g.setColor(oldcolor);
		}
	}
	
	protected void resetCoordinates (int imgW, int ingH)
	{
		
		mScale = DefaultScale;
	}
	
	protected void updateSomeValues (int newScale, int dx, int dy)
	{
		float ratioX;
		float ratioY;
		
		if ( mImageWidth != 0 )
			ratioX = (float) mImageLeft / (float) ( mImageWidth * mScale );
		else
			ratioX = - 0.5f;
		
		if ( mImageHeight != 0 )
			ratioY = (float) mImageTop / (float) ( mImageHeight * mScale );
		else
			ratioY = - 0.5f;
		
		mScale = newScale;
		
		ModuleImage moduleImage = mPureModuleGroup.getModuleImage();
		if ( moduleImage != null && moduleImage.isValid() )
		{
			mImageWidth  = moduleImage.getWidth();
			mImageHeight = moduleImage.getHeight();

			mImageLeft = (int) ( ratioX * (mImageWidth  * mScale) );
			mImageTop  = (int) ( ratioY * (mImageHeight * mScale) );
		}
		else
		{
			mImageLeft = 0;
			mImageTop  = 0;
			mImageWidth  = 0;
			mImageHeight = 0;
			
			return;
		}
		
		mImageLeft += dx;
		mImageTop  += dy;
		
		//
		if ( mImageLeft > 0 )
			mImageLeft = 0;
		if ( mImageTop > 0 )
			mImageTop = 0;
		int imgRight  = mImageLeft + (mImageWidth  * mScale);
		int imgBottom = mImageTop  + (mImageHeight * mScale);
		if ( imgRight < 0 )
			mImageLeft -= imgRight;
		if ( imgBottom < 0 )
			mImageTop -= imgBottom;

	}
	
	protected Point lp2dp (Point lp)
	{
		int viewWidth = getWidth ();
		int viewHeight = getHeight ();
		
		Point dp = new Point ();
		
		dp.x = ( mImageLeft + lp.x * mScale ) + viewWidth / 2;
		dp.y = ( mImageTop  + lp.y * mScale ) + viewHeight / 2;
		
		return dp;
	}
	
	protected void _2dp (Point lp)
	{
		Point dp = lp2dp (lp);
		lp.setLocation (dp);
	}
	
	protected Point dp2lp (Point dp)
	{
		int viewWidth = getWidth ();
		int viewHeight = getHeight ();

		Point lp = new Point ();
		
		lp.x = ( dp.x - viewWidth  / 2 - mImageLeft ) / mScale;
		lp.y = ( dp.y - viewHeight / 2 - mImageTop  ) / mScale;
		
		return lp;
	}
	
	protected void _2lp (Point dp)
	{
		Point lp = dp2lp (dp);
		dp.setLocation (lp);
	}

	protected Dimension ds2ls (Dimension size)
	{
		return new Dimension (size.width / mScale, size.height / mScale);
	}
	
	protected void _2ls (Dimension size)
	{
		Dimension ls = ds2ls (size);
		size.setSize(ls);
	}
	protected Dimension ls2ds (Dimension size)
	{
		return new Dimension (size.width * mScale, size.height * mScale);
	}
	
	protected void _2ds (Dimension size)
	{
		Dimension ds = ls2ds (size);
		size.setSize(ds);
	}
	
//--------------------------------------------------------------------------
// as a PropertyManagerListener
//--------------------------------------------------------------------------

	@Override 
	public void notifyEntityChanged (EntityChangedEvent e)
	{
		if ( e.isChildrenRemovedEvent() && mSelectedModule != null && mSelectedModule.getParent() == null )
		{
			mSelectedModule = null;
		}
		
		
		repaint ();
	}



//--------------------------------------------------------------------------
// as a AncestorListener
//--------------------------------------------------------------------------

	@Override
	public void ancestorAdded(AncestorEvent event) 
	{
		mPureModuleGroup.addEntityObjectListener (this);		
	}

	@Override
	public void ancestorRemoved(AncestorEvent event)  
	{
		mPureModuleGroup.removeEntityObjectListener (this);	
	}
	
	@Override
	public void ancestorMoved(AncestorEvent event) 
	{
		
	}
	
//--------------------------------------------------------------------------
// misc functions related to mouse actions
//--------------------------------------------------------------------------
	
	void setSelectedModule (PureModule selectedModule)
	{
		if ( mSelectedModule != selectedModule )
		{
			mSelectedModule = selectedModule;
			
			if ( mChildrenListView != null && mSelectedModule != null )
				mChildrenListView.setSelectedIndex(mSelectedModule.getIndex());
			
			repaint ();
		}
	}
	
	PureModule getModuleAtPoint (Point point)
	{
		PureModule selectedModule = null;
		
		int from_index = mSelectedModule == null ? 0 : mSelectedModule.getIndex();
		for (int i = mPureModuleGroup.getChildrenCount() - 1; i >= 0; -- i)
		{
			int index = (from_index + i) % mPureModuleGroup.getChildrenCount();
			PureModule module = (PureModule) mPureModuleGroup.getChildByIndex (index);
			int x = module.getX();
			int y = module.getY();
			int w = module.getWidth();
			int h = module.getHeight();
			
			if ( isPointInModule (point, module) )
			{
				selectedModule = module;
				break;
			}
		}
		
		return selectedModule;
	}
	
	boolean isPointInModule (Point point, PureModule module)
	{
		if ( module == null )
			return false;
		
		int x = module.getX();
		int y = module.getY();
		int w = module.getWidth();
		int h = module.getHeight();
		
		Point lp = dp2lp (point);
		if ( x <= lp.x && lp.x < x + w && y <= lp.y && lp.y < y + h )
		{
			return true;
		}
		
		return false;
	}
	
	int mCursorRegion = Region_None;
	
	final static int ModuleBorderMarginSize = 1;
	final static int Region_None = -1;
	final static int Region_BorderLeft = 0;
	final static int Region_BorderRight = 1;
	final static int Region_BorderTop = 2;
	final static int Region_CornerTopLeft = 3;
	final static int Region_CornerBottomLeft = 4;
	final static int Region_CornerTopRight = 5;
	final static int Region_CornerBottomRight = 6;
	final static int Region_BorderBottom = 7;
	final static int Region_InModule = 8;
	final static int Region_InImage = 9;

	void updateCursor (Point point, boolean bStartAction)
	{
//		if ( mReadOnly )
//			return;
		
		ModuleImage pureImage = mPureModuleGroup.getModuleImage();
		if ( pureImage != null && pureImage.isValid() )
		{
	
			if (mSelectedModule != null)
			{
				int x = mSelectedModule.getX();
				int y = mSelectedModule.getY();
				int w = mSelectedModule.getWidth();
				int h = mSelectedModule.getHeight();
				
				Point top_left     = new Point (x, y);
				Point bottom_right = new Point (x + w, y + h);
				
				_2dp (top_left);
				_2dp (bottom_right);
				
				boolean canResizeModule = true;
				
				// corners
				if ( point.x >= top_left.x - ModuleBorderMarginSize && point.x <= top_left.x + ModuleBorderMarginSize
						 && point.y >= top_left.y - ModuleBorderMarginSize && point.y < top_left.y + ModuleBorderMarginSize)
				{
					mCursorRegion =  Region_CornerTopLeft;
					setCursor (Cursor.getPredefinedCursor(Cursor.NW_RESIZE_CURSOR));
				}
				else if ( point.x >= top_left.x - ModuleBorderMarginSize && point.x <= top_left.x + ModuleBorderMarginSize
						 && point.y >= bottom_right.y - ModuleBorderMarginSize && point.y < bottom_right.y + ModuleBorderMarginSize)
				{
					mCursorRegion =  Region_CornerBottomLeft;
					setCursor (Cursor.getPredefinedCursor(Cursor.SW_RESIZE_CURSOR));
				}
				else if ( point.x >= bottom_right.x - ModuleBorderMarginSize && point.x <= bottom_right.x + ModuleBorderMarginSize
						 && point.y >= top_left.y - ModuleBorderMarginSize && point.y < top_left.y + ModuleBorderMarginSize )
				{
					mCursorRegion =  Region_CornerTopRight;
					setCursor (Cursor.getPredefinedCursor(Cursor.NE_RESIZE_CURSOR));
				}
				else if ( point.x >= bottom_right.x - ModuleBorderMarginSize && point.x <= bottom_right.x + ModuleBorderMarginSize
						 && point.y >= bottom_right.y - ModuleBorderMarginSize && point.y < bottom_right.y + ModuleBorderMarginSize)
				{
					mCursorRegion =  Region_CornerBottomRight;
					setCursor (Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR));
				}
				
				// borders
				else if ( point.x >= top_left.x - ModuleBorderMarginSize && point.x <= top_left.x + ModuleBorderMarginSize
						 && point.y >= top_left.y && point.y < bottom_right.y )
				{
					mCursorRegion =  Region_BorderLeft;
					setCursor (Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR));
				}
				else if ( point.x >= bottom_right.x - ModuleBorderMarginSize && point.x <= bottom_right.x + ModuleBorderMarginSize
						 && point.y >= top_left.y && point.y < bottom_right.y )
				{
					mCursorRegion =  Region_BorderRight;
					setCursor (Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR));
				}
				else if ( point.y >= top_left.y - ModuleBorderMarginSize && point.y <= top_left.y + ModuleBorderMarginSize
						 && point.x >= top_left.x && point.x < bottom_right.x )
				{
					mCursorRegion =  Region_BorderTop;
					setCursor (Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR));
				}
				else if ( point.y >= bottom_right.y - ModuleBorderMarginSize && point.y <= bottom_right.y + ModuleBorderMarginSize
						 && point.x >= top_left.x && point.x < bottom_right.x )
				{
					mCursorRegion =  Region_BorderBottom;
					setCursor (Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR));
				}
				else
				{
					canResizeModule = false;
				}
				
				if ( canResizeModule )
				{
					if ( bStartAction )
					{
						startResizingSelectedModule(point);
					}
					
					return;
				}
				
				// in module
				if ( point.y >= top_left.y && point.y <= bottom_right.y
						 && point.x >= top_left.x && point.x < bottom_right.x )
				{
					mCursorRegion =  Region_InModule;
					setCursor (Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
					
					if ( bStartAction )
					{
						startMovingSelectedModule (point);
					}
					
					return;
				}
				
			}
			
			// in image		
			int viewWidth = getWidth ();
			int viewHeight = getHeight ();
			if (point.x >= mImageLeft + viewWidth / 2 && point.x < mImageLeft + viewWidth / 2 + mImageWidth * mScale
				&& point.y >= mImageTop + viewHeight / 2 && point.y < mImageTop + viewHeight / 2 + mImageHeight * mScale
					)
			{
				mCursorRegion =  Region_InImage;
				setCursor (Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
				
				if ( bStartAction )
				{
					startTempModule (point);
				}
				
				return;
			}
		}
		
		mCursorRegion = Region_None;
		setCursor (Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
	}

	
	boolean mMovingImage = false;	
	int mLastImageX;
	int mLastImageY;
	Point mRightButtonStartPoint = new Point ();

	void startMovingImage (Point startDevice)
	{
		mMovingImage = true;
		mRightButtonStartPoint.setLocation(startDevice);
		
		mLastImageX = mImageLeft;
		mLastImageY = mImageTop;
	}
	
	void updateMovingImage (Point point)
	{
		  updateSomeValues (mScale, 
				  mLastImageX + point.x - mRightButtonStartPoint.x - mImageLeft,
				  mLastImageY + point.y - mRightButtonStartPoint.y - mImageTop
				  );
		  
			
		  setCursor (Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
		  
		  repaint ();
	}
	
	void endMovingImage ()
	{
		mMovingImage = false;
	}
	
	boolean mCreatingNewModule = false;
	Point mLeftButtonStartPoint = new Point ();
	PureModule mTempModule;
	long mStartTempModuleTime;
	boolean mEndTempModuleWhenReleaseLeftButton; // false: end when press left button again
	
	void startTempModule (Point startDevice)
	{
		if ( mReadOnly )
		{
			setSelectedModule ( getModuleAtPoint ( startDevice ) );
			return;
		}
		
		ModuleImage moduleImage = mPureModuleGroup.getModuleImage();
		if ( moduleImage != null && moduleImage.isValid() )
		{
			mCreatingNewModule = true;
		  	mLeftButtonStartPoint.setLocation (startDevice);
		  	
		  	mStartTempModuleTime = System.currentTimeMillis();
		  	mEndTempModuleWhenReleaseLeftButton = false;
		}
	}
	
	void cancelTempModule ()
	{
		mCreatingNewModule = false;
		mTempModule = null;
		mEndTempModuleWhenReleaseLeftButton = false;
		
		repaint();
	}

	void updateTempModule (Point endDevice)
	{
		Point start = dp2lp (mLeftButtonStartPoint);
		Point end   = dp2lp (endDevice);
		if ( start.x > end.x)
		{
			int x = end.x;
			end.x = start.x;
			start.x = x;
		}
		  
		if ( start.y > end.y)
		{
			int y = end.y;
			end.y = start.y;
			start.y = y;
		}
		
		if (mTempModule == null)
			mTempModule = new PureModule (0, 0, 0, 0);

		mTempModule.setProperties (
				start.x, 
				start.y, 
				end.x - start.x, 
				end.y -  start.y
		);
		
	}
	

	
	void endTempModule (Point endDevice)
	{
		mCreatingNewModule = false;
		
		if ( System.currentTimeMillis() - mStartTempModuleTime < 250 )
		{
			setSelectedModule ( getModuleAtPoint ( endDevice ) );
		}
		else if ( mTempModule.getWidth() > 0 && mTempModule.getHeight() > 0 ) 
		{
			ModuleImage moduleImage = mPureModuleGroup.getModuleImage();
			if ( moduleImage != null && moduleImage.isValid() )
			{
				mSelectedModule = mPureModuleGroup.createNewModule(mTempModule.getX(), mTempModule.getY(), mTempModule.getWidth(), mTempModule.getHeight());
				mTempModule = null;
	
				mPureModuleGroup.commitModifications();
			}
		}
		
		cancelTempModule ();
	}

	boolean mMovingSelectedModule;
	int mLastSelectedModuleX;
	int mLastSelectedModuleY;
	
	void startMovingSelectedModule (Point startDevice)
	{
		logger.assertLog(mSelectedModule != null, "mSelectedModule should not be null");
		
		mMovingSelectedModule = true;
		
		mLastSelectedModuleX = mSelectedModule.getX();
		mLastSelectedModuleY = mSelectedModule.getY();
		
		mLeftButtonStartPoint.setLocation (startDevice);
	}
	
	void updateMovingSelectedModule (Point endDevice)
	{
		logger.assertLog(mSelectedModule != null, "mSelectedModule should not be null");
		logger.assertLog(mMovingSelectedModule, "mMovingSelectedModule = false, !?");

		if ( mSelectedModule == null )
			return;
		
		int dx = endDevice.x - mLeftButtonStartPoint.x;
		int dy = endDevice.y - mLeftButtonStartPoint.y;
		Dimension dSize = new Dimension (dx, dy);
		_2ls (dSize);
		
		mSelectedModule.setX (mLastSelectedModuleX + dSize.width);
		mSelectedModule.setY (mLastSelectedModuleY + dSize.height);
		
		mSelectedModule.commitModifications();

		//repaint ();
	}
	
	void endMovingSelectedModule ()
	{
		mMovingSelectedModule = false;
	}
	
	
	boolean mResizingSelectedModule;
	int mLastSelectedModuleRight;
	int mLastSelectedModuleBottom;

	void startResizingSelectedModule (Point startDevice)
	{
		logger.assertLog(mSelectedModule != null, "mSelectedModule should not be null");
		
		mResizingSelectedModule = true;
		mLeftButtonStartPoint.setLocation(startDevice);
		
		mLastSelectedModuleX = mSelectedModule.getX();
		mLastSelectedModuleY = mSelectedModule.getY();
		mLastSelectedModuleRight = mSelectedModule.getX() + mSelectedModule.getWidth();
		mLastSelectedModuleBottom = mSelectedModule.getY() + mSelectedModule.getHeight();
	}
	
	void updateResizingSelectedModule (Point endDevice)
	{
		logger.assertLog(mSelectedModule != null, "mSelectedModule should not be null");
		logger.assertLog(mResizingSelectedModule, "mResizingSelectedModule = false, !?");
		
		int dx = endDevice.x - mLeftButtonStartPoint.x;
		int dy = endDevice.y - mLeftButtonStartPoint.y;
		Dimension dSize = new Dimension (dx, dy);
		_2ls (dSize);

		int l, t, r, b;
		
		switch (mCursorRegion)
		{
		case Region_BorderLeft:
		case Region_CornerTopLeft:
		case Region_CornerBottomLeft:
			l = mLastSelectedModuleX + dSize.width;
			r = mLastSelectedModuleRight;
			if ( l >= r )
				l = r - 1;
			break;
		case Region_BorderRight:
		case Region_CornerTopRight:
		case Region_CornerBottomRight:
			l = mLastSelectedModuleX;
			r = mLastSelectedModuleRight + dSize.width;
			if ( r <= l )
				r = l + 1;
			break;
		case Region_BorderTop:
		case Region_BorderBottom:
			l = mLastSelectedModuleX;
			r = mLastSelectedModuleRight;
			break;
		default:
			return;
		}
		
		switch (mCursorRegion)
		{
		case Region_BorderTop:
		case Region_CornerTopLeft:
		case Region_CornerTopRight:
			t = mLastSelectedModuleY + dSize.height;
			b = mLastSelectedModuleBottom;
			if  ( t >= b )
				t = b - 1;
			break;
		case Region_BorderBottom:
		case Region_CornerBottomLeft:
		case Region_CornerBottomRight:
			t = mLastSelectedModuleY;
			b = mLastSelectedModuleBottom + dSize.height;
			if ( b <= t )
				b = t + 1;
			break;
		case Region_BorderLeft:
		case Region_BorderRight:
			t = mLastSelectedModuleY;
			b = mLastSelectedModuleBottom ;
			break;
		default:
			return;
		}
		
		mSelectedModule.setProperties(l, t, r - l, b - t);
		mSelectedModule.commitModifications();
	}
	
	
	void endResizingSelectedModule ()
	{
		mResizingSelectedModule = false;
	}
	
	
//--------------------------------------------------------------------------
// as a MouseListener
//--------------------------------------------------------------------------

	
	// Method descriptor #12 (Ljava/awt/event/MouseEvent;)V
	public void mouseClicked(java.awt.event.MouseEvent e)
	{
		if (e.getButton () == e.BUTTON3)
		{
			setSelectedModule ( getModuleAtPoint ( e.getPoint() ) );
			
			if ( mReadOnly )
			{
				JPopupMenu popMenu = new JPopupMenu();
				AbstractAction action = new ReplaceModuleInPartAction (); 
				popMenu.add ( action );
				

				ModuleRef part = SharedData.sSelectedModuleRef;
				
				action.setEnabled(part != null && part.checkReferability(mSelectedModule));
				
				popMenu.show(this, e.getX(), e.getY());
			}
		}
	}
	  
	// Method descriptor #12 (Ljava/awt/event/MouseEvent;)V
	public void mousePressed(java.awt.event.MouseEvent e)
	{
		//PureModule module = getModuleAtPoint ( e.getPoint() );
		
		if (e.getButton () == e.BUTTON1)
		{
			updateCursor (e.getPoint(), true);
		}
		  
		if (e.getButton () == e.BUTTON3)
		{			
			startMovingImage (e.getPoint());
			  
			cancelTempModule ();
		}
	}
	  
	// Method descriptor #12 (Ljava/awt/event/MouseEvent;)V
	public void mouseReleased(java.awt.event.MouseEvent e)
	{
		if (e.getButton () == e.BUTTON1)
		{
			if ( mResizingSelectedModule )
			{
				updateResizingSelectedModule (e.getPoint());
				endResizingSelectedModule ();
			}
			
			if ( mMovingSelectedModule )
			{
				updateMovingSelectedModule (e.getPoint());				  
				endMovingSelectedModule ();
			}
			  
			  
			if ( mCreatingNewModule )
			{
				updateTempModule (e.getPoint());
				endTempModule (e.getPoint());
			}
		}
		  
		if (e.getButton () == e.BUTTON3)
		{			
			if (mMovingImage)
			{
				updateMovingImage (e.getPoint());
				endMovingImage ();
			}

			cancelTempModule ();
		}
		
		updateCursor (e.getPoint(), false);		  
	}
	  
	// Method descriptor #12 (Ljava/awt/event/MouseEvent;)V
	public void mouseEntered(java.awt.event.MouseEvent e)
	{
		
	}
	  
	// Method descriptor #12 (Ljava/awt/event/MouseEvent;)V
	public void mouseExited(java.awt.event.MouseEvent e)
	{
		
	}
	  
//--------------------------------------------------------------------------
// as a MouseMotionListener
//--------------------------------------------------------------------------

	// Method descriptor #9 (Ljava/awt/event/MouseEvent;)V
	public void mouseDragged(java.awt.event.MouseEvent e)
	{
		if (mMovingImage)
			updateMovingImage (e.getPoint());
		
		if (mResizingSelectedModule)
			updateResizingSelectedModule (e.getPoint());
		  
		if ( mMovingSelectedModule )
			updateMovingSelectedModule (e.getPoint());
		  
		if ( mCreatingNewModule )
		{
			updateTempModule (e.getPoint());
			repaint ();
		}
	}
	  
	  // Method descriptor #9 (Ljava/awt/event/MouseEvent;)V
	public void mouseMoved(java.awt.event.MouseEvent e)
	{
		updateCursor (e.getPoint(), false);
	}
	  
//--------------------------------------------------------------------------
// as a MouseWheelListener
//--------------------------------------------------------------------------

	// Method descriptor #8 (Ljava/awt/event/MouseWheelEvent;)V
	public void mouseWheelMoved(java.awt.event.MouseWheelEvent event)
	{
		float scale = (float)mScale + ( event.getWheelRotation () > 0 ? 1 : -1 );
		
		if ( scale < MinScale)
			scale = MinScale;
		if (scale > MaxScale)
			scale = MaxScale;

		updateSomeValues ((int)scale, 0, 0);
		repaint ();
	}
	  
	
//--------------------------------------------------------------------------
	
	class ReplaceModuleInPartAction extends AbstractAction 
	{
		public ReplaceModuleInPartAction ()
		{
			super ("Replaced by This One");
		}
		
	    public void actionPerformed(ActionEvent e) 
	    {
	    	ModuleRef part = SharedData.sSelectedModuleRef;
			part.setModule (mSelectedModule);
			part.commitModifications();
	    }
	}
}
